#!/bin/sh -efu
#
# Copyright (C) 2008-2018  Alexey Gladkov <legion@altlinux.org>
# Copyright (C) 2008,2009  Dmitry V. Levin <ldv@altlinux.org>
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
#

. gear-utils-sh-functions

specfile="${gear_specfile##*/}"
verbose="${gear_verbose-}"

outdir="${gear_command_outdir:-out}"
target="${gear_command_target-}"
server="${gear_command_server-}"
workdir="${gear_command_workdir-}"
method="${gear_command_method-}"

not_remote_repo=1
[ -z "${gear_command_remote_repo-}" ] || not_remote_repo=

args=
remote_srcdir=

detect_method()
{
	# shellcheck disable=SC2087
	ssh "$server" "sh -efu"<<-EOF
	${verbose:+set -x}
	cd '$workdir'
	for t in gear hsh rpm; do
	   [ -d "$gear_pkg_name#\$t" ] || continue
	   m="\$t"
	   break
	done
	echo "\${m:-gear}"
	EOF
}

canonicalize_workdir()
{
	# shellcheck disable=SC2029
	workdir="$(ssh "$server" "cd -- \"$(quote_shell "$1")\" && pwd -P")" ||
		fatal "$server:$1: directory not available"
}

remote_prepare()
{
	# shellcheck disable=SC2087
	ssh "$server" "sh -efu"<<-EOF
	rm -rf -- '$workdir/out'
	mkdir $verbose -p -- \
		${not_remote_repo:+'$workdir/out/bin'} \
		${not_remote_repo:+'$workdir/out/src'} \
		'$workdir/build' \
		'$remote_srcdir'
	EOF
}

remote_cleanup()
{
	# shellcheck disable=SC2087
	ssh "$server" "sh -eu"<<-EOF
	${verbose:+set -x}
	! type -p hsh >/dev/null ||
		hsh --cleanup -- '$workdir/build'
	rm -rf -- '$workdir/out' '$workdir/$gear_pkg_name#'* '$workdir/build'
	EOF
}

remote_hsh()
{
	local pkgname="${gear_outfile##*/}"

	tar --create --file="$gear_outfile" --directory="$gear_outdir" \
		--label="$specfile" --owner=root --group=root \
		--mode=u+w,go-w,go+rX $gear_tar_compress .

	verbose "Created output tarball: $pkgname"
	rsync $verbose -rtlp "$gear_outfile" "$server:$remote_srcdir/"

	# Once tarball is created, its sources are no longer needed.
	rm -f -- "$gear_outfile"

	# shellcheck disable=SC2087
	ssh "$server" "sh -efu"<<-EOF
	${verbose:+set -x}
	cd '$remote_srcdir'
	$target \
	   hsh $args \
	      ${target:+--target='$target'} \
	      ${not_remote_repo:+--repo-bin='$workdir/out/bin'} \
	      ${not_remote_repo:+--repo-src='$workdir/out/src'} \
	      -- '$workdir/build' '$remote_srcdir/$pkgname'
	EOF
}

remote_gear()
{
	# shellcheck disable=SC2087
	ssh "$server" "sh -efu"<<-EOF
	${verbose:+set -x}
	[ -d '$remote_srcdir/.git' ] ||
	   git --git-dir='$remote_srcdir/.git' init
	EOF

	if ! git push --thin "$server:$remote_srcdir" "$gear_commit_id":refs/heads/master 2>/dev/null; then
		verbose "Invalid remote git repository"

		# shellcheck disable=SC2087
		ssh "$server" "sh -efu"<<-EOF
		rm -rf -- '$remote_srcdir/.git'
		git --git-dir='$remote_srcdir/.git' init
		EOF

		git push --thin "$server:$remote_srcdir" "$gear_commit_id":refs/heads/master
	fi

	# shellcheck disable=SC2087
	ssh "$server" "sh -efu"<<-EOF
	${verbose:+set -x}
	cd '$remote_srcdir'
	$target \
	   gear $verbose --hasher -- \
	      hsh $args \
	         ${target:+--target='$target'} \
	         ${not_remote_repo:+--repo-bin='$workdir/out/bin'} \
	         ${not_remote_repo:+--repo-src='$workdir/out/src'} \
	         -- '$workdir/build'
	EOF
}

remote_rpm()
{
	rsync $verbose -rtlp "$gear_outdir/" "$server:$remote_srcdir/"

	# shellcheck disable=SC2087
	ssh "$server" "sh -efu"<<-EOF
	${verbose:+set -x}
	cd '$workdir/build'

	rm -rf -- BUILD RPMS SRPMS temp
	mkdir -p -- BUILD RPMS SRPMS temp

	$target \
	   rpmbuild $args -ba \
	   ${target:+--target='$target'} \
	   --define "_topdir $workdir/build" \
	   --define "_tmppath $workdir/temp" \
	   --define "_specdir $remote_srcdir" \
	   --define "_sourcedir $remote_srcdir" \
	   '$remote_srcdir/$specfile'

	find '$workdir/build/RPMS' -type f -name '*.rpm' |
		xargs -ri mv $verbose -f '{}' '$workdir/out/bin'

	find '$workdir/build/SRPMS' -type f -name '*src.rpm' |
		xargs -ri mv $verbose -f '{}' '$workdir/out/src'
	EOF
}

cleanup_handler()
{
	[ -z "${gear_command_cleanup-}" ] ||
		remote_cleanup
}

[ -n "$method" ] ||
	method="$(detect_method)"

case "$method" in
	hsh|rpm|gear) ;;
	*) fatal "Unknown build method: $method" ;;
esac

canonicalize_workdir "$workdir"
remote_srcdir="$workdir/$gear_pkg_name#$method"
install_cleanup_handler cleanup_handler

args=
while [ $# -gt 0 ]; do
	args="$args \"$(quote_shell "$1")\""
	shift
done

remote_prepare
remote_$method

[ -n "${gear_command_build_only-}" ] || [ -z "$not_remote_repo" ] ||
	rsync $verbose -rtlp "$server:$workdir/out/" "$outdir/"
